001 /** 002 * Copyright 2004 The Apache Software Foundation 003 * Copyright 2005 Stephen McConnell 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package net.dpml.cli.commandline; 018 019 import java.util.ArrayList; 020 import java.util.Arrays; 021 import java.util.Collections; 022 import java.util.HashSet; 023 import java.util.Iterator; 024 import java.util.List; 025 import java.util.Set; 026 import java.util.StringTokenizer; 027 import java.util.prefs.BackingStoreException; 028 import java.util.prefs.Preferences; 029 030 import net.dpml.cli.Option; 031 032 /** 033 * A CommandLine implementation using the Preferences API, useful when 034 * constructing a complex DefaultingCommandLine 035 * 036 * This implementation uses the children of a single preference node to populate 037 * the CommandLine. Options are keyed from their preferred name and presence in 038 * the Preferences object is taken as presence in the CommandLine. Argument 039 * values are taken from the Preference value and are optionally separated using 040 * the separator char defined, at construction time. Switch values can be 041 * specified using a simple value of <code>true</code> or <code>false</code>; 042 * obviously this means that Switches with Arguments are not supported by this 043 * implementation. 044 * 045 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 046 * @version 1.0.0 047 * @see java.util.prefs.Preferences 048 * @see net.dpml.cli.commandline.DefaultingCommandLine 049 * @see net.dpml.cli.Option#getPreferredName() 050 */ 051 public class PreferencesCommandLine extends CommandLineImpl 052 { 053 private static final char NUL = '\0'; 054 private final Preferences m_preferences; 055 private final Option m_root; 056 private final char m_separator; 057 058 /** 059 * Creates a new PreferencesCommandLine using the specified root Option and 060 * Preferences node. Argument values will be separated using the char 0. 061 * 062 * @param root the CommandLine's root Option 063 * @param preferences the Preferences node to get values from 064 */ 065 public PreferencesCommandLine( final Option root, final Preferences preferences ) 066 { 067 this( root, preferences, NUL ); 068 } 069 070 /** 071 * Creates a new PreferencesCommandLine using the specified root Option, 072 * Preferences node and value separator. 073 * 074 * @param root the CommandLine's root Option 075 * @param preferences the Preferences node to get values from 076 * @param separator the character to split argument values 077 */ 078 public PreferencesCommandLine( 079 final Option root, final Preferences preferences, final char separator ) 080 { 081 m_root = root; 082 m_preferences = preferences; 083 m_separator = separator; 084 } 085 086 /** 087 * Detects the presence of an option in this CommandLine. 088 * 089 * @param option the Option to search for 090 * @return true iff the option is present 091 */ 092 public boolean hasOption( Option option ) 093 { 094 if( option==null ) 095 { 096 return false; 097 } 098 else 099 { 100 try 101 { 102 return Arrays.asList( m_preferences.keys() ).contains( option.getPreferredName() ); 103 } 104 catch( BackingStoreException e ) 105 { 106 return false; 107 } 108 } 109 } 110 111 /** 112 * Finds the Option with the specified trigger 113 * 114 * @param trigger the name of the option to retrieve 115 * @return the Option matching the trigger or null if none exists 116 */ 117 public Option getOption( String trigger ) 118 { 119 return m_root.findOption( trigger ); 120 } 121 122 /** 123 * Retrieves the Argument values associated with the specified Option 124 * 125 * @param option the Option associated with the values 126 * @param defaultValues the result to return if no values are found 127 * @return a list of values or defaultValues if none are found 128 */ 129 public List getValues( final Option option, final List defaultValues ) 130 { 131 final String value = m_preferences.get( option.getPreferredName(), null ); 132 if( value==null ) 133 { 134 return defaultValues; 135 } 136 else if( m_separator>NUL ) 137 { 138 final List values = new ArrayList(); 139 final StringTokenizer tokens = new StringTokenizer( value, String.valueOf( m_separator ) ); 140 141 while( tokens.hasMoreTokens() ) 142 { 143 values.add( tokens.nextToken() ); 144 } 145 146 return values; 147 } 148 else 149 { 150 return Collections.singletonList( value ); 151 } 152 } 153 154 /** 155 * Retrieves the Boolean value associated with the specified Switch 156 * 157 * @param option the Option associated with the value 158 * @param defaultValue the Boolean to use if none match 159 * @return the Boolean associated with option or defaultValue if none exists 160 */ 161 public Boolean getSwitch( final Option option, final Boolean defaultValue ) 162 { 163 final String value = m_preferences.get( option.getPreferredName(), null ); 164 if( "true".equals( value ) ) 165 { 166 return Boolean.TRUE; 167 } 168 else if( "false".equals( value ) ) 169 { 170 return Boolean.FALSE; 171 } 172 else 173 { 174 return defaultValue; 175 } 176 } 177 178 /** 179 * Retrieves the value associated with the specified property 180 * 181 * @param property the property name to lookup 182 * @param defaultValue the value to use if no other is found 183 * @return the value of the property or defaultValue 184 */ 185 public String getProperty( final String property, final String defaultValue ) 186 { 187 return m_preferences.get( property, defaultValue ); 188 } 189 190 /** 191 * Retrieves the set of all property names associated with this CommandLine 192 * 193 * @return a none null set of property names 194 */ 195 public Set getProperties() 196 { 197 try 198 { 199 return new HashSet( Arrays.asList( m_preferences.keys() ) ); 200 } 201 catch( BackingStoreException e ) 202 { 203 return Collections.EMPTY_SET; 204 } 205 } 206 207 /** 208 * Retrieves a list of all Options found in this CommandLine 209 * 210 * @return a none null list of Options 211 */ 212 public List getOptions() 213 { 214 try 215 { 216 final List options = new ArrayList(); 217 final Iterator keys = Arrays.asList( m_preferences.keys() ).iterator(); 218 while( keys.hasNext() ) 219 { 220 final String trigger = (String) keys.next(); 221 final Option option = m_root.findOption( trigger ); 222 if( option != null ) 223 { 224 options.add( option ); 225 } 226 } 227 return Collections.unmodifiableList( options ); 228 } 229 catch( BackingStoreException e ) 230 { 231 return Collections.EMPTY_LIST; 232 } 233 } 234 235 /** 236 * Retrieves a list of all Option triggers found in this CommandLine 237 * 238 * @return a none null list of Option triggers 239 */ 240 public Set getOptionTriggers() 241 { 242 final Set triggers = new HashSet(); 243 final Iterator options = getOptions().iterator(); 244 while( options.hasNext() ) 245 { 246 final Option option = (Option) options.next(); 247 triggers.addAll( option.getTriggers() ); 248 } 249 return Collections.unmodifiableSet( triggers ); 250 } 251 }